import { PhysicsSystem, director, Director } from "cc";

let subStepCount = 0;
let accumulator = 0;
let postUpdateStepCount = 0;
const maxSubSteps = 5;
const MAX_STEPS = 600;

export class FixedPhysics {
    public static EVENT_UPDATE_FINISHED = 'FixedPhysics.EVENT_UPDATE_FINISHED';

    public static reset(){
        subStepCount = 0;
        accumulator = 0;
        postUpdateStepCount = 0;
        PhysicsSystem.instance.autoSimulation = false;
        PhysicsSystem.instance.fixedTimeStep = 0.01;
        PhysicsSystem.instance.maxSubSteps = 5;
    }
    public static fixedUpdate(dt: number) {
        if (!PhysicsSystem.instance.physicsWorld) return;
        if (!PhysicsSystem.instance.enable) {
            PhysicsSystem.instance.physicsWorld.syncSceneToPhysics();
            return;
        }
        subStepCount = 0;
        accumulator += dt;
        director.emit(Director.EVENT_BEFORE_PHYSICS);
        while ((subStepCount < maxSubSteps)) {
            if (postUpdateStepCount < MAX_STEPS && accumulator >= PhysicsSystem.instance.fixedTimeStep) {
                PhysicsSystem.instance.physicsWorld.syncSceneToPhysics();
                PhysicsSystem.instance.physicsWorld.step(PhysicsSystem.instance.fixedTimeStep);
                PhysicsSystem.instance.physicsWorld.emitEvents();
                PhysicsSystem.instance.physicsWorld.syncAfterEvents();
                accumulator -= PhysicsSystem.instance.fixedTimeStep;
                subStepCount++;
                postUpdateStepCount++;
            }
            else {
                PhysicsSystem.instance.physicsWorld.syncSceneToPhysics();
                break;
            }
        }
        if (postUpdateStepCount === MAX_STEPS) {
            director.getScene().emit(FixedPhysics.EVENT_UPDATE_FINISHED);
        }
        director.emit(Director.EVENT_AFTER_PHYSICS);
    }
}